#!/bin/sh
#
#  @file rtm-naming
#  @brief OpenRTM-aist name server launcher
#  @date $Date: 2005-05-12 09:06:19 $
#  @author Noriaki Ando <n-ando@aist.go.jp>
#
#  Copyright (C) 2003-2018
#      Intelligent Systems Research Institute,
#      National Institute of
#          Advanced Industrial Science and Technology (AIST), Japan
#      All rights reserved.
#
#  $Id$
#

cosnames="@COSNAMES@"
orb="@CORBA@"

pname=`basename $cosnames`
hostname=`hostname`
currdir=`pwd`
DEBUG=""

usage()
{
    cat<<EOF

  Usage:
    $(basename $0) [-p port_number] [-f] [-w password] [h]

  Example:
    $(basename $0) -p 8888 -f
      Force running naming service on port 8888

  Options:
    -p         Port number of naming service. (default 2809)
    -f         Force kill current running naming service.
    -k         Stop existing naming service.
    -w         Current user's passoword to restart naming service.
    -h         Print this help.

EOF
}

get_opt()
{
    # Global variables
    FORCEKILL=""
    PASSWORD=""
    PORT=2809
    if test $# -eq 0 ; then
        PORT=2809
    fi

    while getopts p:fkw:h OPT
    do
        case $OPT in
            p) PORT=$OPTARG
                ;;
            f) FORCEKILL="YES"
                ;;
            k) STOPNAMESERVICE="YES"
                ;;
            w) PASSWORD=$OPTARG
                ;;
            h) usage
                exit 1
                ;;
        esac
    done
}
#
# debug <text>
#
# Debug print. If variable "DEBUG" is defined, text will be printed.
#
# @param text to be printed.
#
debug()
{
    if test "x$DEBUG" != "x"; then
        echo $*
    fi
}

#
# get_pid_of_nsport <port_number>
#
# @param  pid_of_nsport: Process ID of a process which is using the port.
# @param  pname_of_nsport: Process name which is using the port is set
# @param  pid_of_nsport: Process ID which is using the port is set
# @return 0 process that is using the port was found
#         1 process not found
#
#
get_pid_of_nsport()
{
    _port=$1
    debug "netstat -tlnp 2> /dev/null | grep $_port | awk '{print $7;}'"
    netstat_tanp=`netstat -tlnp`
    if test "x$PASSWORD" = "x"; then
        _netstat=`sudo netstat -tlnp 2> /dev/null | grep $_port | awk '{if($7!="-"){print $7;}}'`
    else
        _netstat=`echo $PASSWORD | sudo -S netstat -tlnp 2> /dev/null | grep $_port | awk '{if($7!="-"){print $7;}}'`
    fi
    debug "A possible process that is using $_port port:" $_netstat
    if test "x$_netstat" = "x"; then
        echo "No process using port number ${_port} on the system."
        debug "No process using port number ${_port} on the system."
        return 1
    fi

    _pid=`echo $_netstat | awk 'BEGIN{FS="/";}{print $1;}'`
    pname_of_nsport=`echo $_netstat | awk 'BEGIN{FS="/";}{print $2;}'`
    pid_of_nsport=$_pid
    debug "$_port port is used by $pname_of_nsport (pid = $_pid)."
    return 0
}


#
# is_launch_from_init <prog_name> (<pid>)
#
# @param prog_name The name of the program
# @param pid The pid of the program
# @param init_script A path to init script is set
# @return 0: The program might be started from init script
#         1: The program might not be started from init script
# 
is_started_from_init()
{
    debug "number of args" $#
    if test $# -eq 2; then
	_pname=$1
	_pid=$2
    elif test $# -eq 1; then
	debug "pid is not specified. It is obtained from pid file."
	_pname=$1
	_pid=`cat /var/run/$_pname.pid`
    elif test $# -eq 0; then
	debug "No program name specified."
    fi

    if test -f /var/run/$_pname.pid; then
	debug "pid file: /var/run/$_pname.pid found"
	_var_run_pid=`cat /var/run/$_pname.pid`

	debug "specified pid:        " $_pid
	debug "/var/run/$_pname.pid: " $_var_run_pid 

	if test $_pid -eq $_var_run_pid; then
	    debug "The process $_pname ($_pid) might be started " \
		"from init script."
	    debug "searching init script: $cosnames"
	    init_script=`grep $cosnames /etc/init.d/* | awk 'BEGIN{FS=":";}{if(FNR==1){print $1;}}'`

	    if test "x$init_script" = "x"; then

		echo "Init script not found. Aborting"
		exit 1
	    fi
	    debug "Init script found: $init_script"
	    return 0
	fi

	debug "The process $_pname ($_pid) might not be started " \
	    "from init script."
	return 1
    fi
    debug "/var/run/$_pname.pid not found."
    return 1
}


#
# check_cosname
#
# Checking if global variable "cosname" is set.
#
check_cosname()
{
    if test ! -f $cosnames ; then
	echo "Name service program ($cosnames) not found."
	echo "Please install or chech rtm-naming script."
	exit 1
    fi
}

delete_omninames_files()
{
    if test "x$PASSWORD" = "x" ; then
        rm -f ./omninames-$hostname.log
        rm -f ./omninames-$hostname.bak
        rm -f ./omninames-$hostname.dat
    else
        echo $PASSWORD | sudo -S rm -f ./omninames-$hostname.log
        echo $PASSWORD | sudo -S rm -f ./omninames-$hostname.bak
        echo $PASSWORD | sudo -S rm -f ./omninames-$hostname.dat
    fi
    debug "omninames-$hostname files deleted."
}

#
# specified_port_used_check
#
# Find a process which is using specified port.
#
specified_port_used_check()
{
    get_pid_of_nsport $PORT
    if test $? -eq 0; then
        debug "The Process information using the port could be obtained."
        # If "port" is used by other program -> abort

        pids=`pgrep $pname`
        matchflag=0
        for p in $pids; do
            if test "x$pid_of_nsport" = "x$p"; then
                matchflag=1
            fi
        done
        if test $matchflag -eq 0; then
            echo "$pname_of_nsport (not $pname) is using the port."
            echo "Starting $pname aborted. Please use the other port."
            exit 1
        fi
    else
        debug "The process information using the port could not be obtained."
        exit 1
    fi
}

#
# stop omninames by init script
#
# Process is started from the init script, it tries to stop it
# by the script.
#
stop_omninames_by_init_script()
{
    echo "omniNames might be started $init_script."

    if test "x$FORCEKILL" = "x" && test "x$STOPNAMESERVICE" = "x" ; then
        echo "Stop it (password for sudo is required.)"
        read -p "and start omniNames by rtm-naming? (y/N)" startns
        if test "x$startns" != "xy" -a "x$startns" != "xY" ; then
            echo "Aborted."
            exit 1
        fi
    fi
    echo "Stopping omniNames by $init_script."
    if test "x$PASSWORD" = "x" ; then
       sudo $init_script stop
       sudo rm -f /var/run/$pname.pid
    else
        echo $PASSWORD | sudo -S $init_script stop
        echo $PASSWORD | sudo -S rm -f /var/run/$pname.pid
    fi
    debug "$init_script stop"
    debug "/var/run/$pname.pid  are deleted"
    delete_omninames_files
    return 0

}

#
# stop_existing_ns
#
# This function try to stop existing nameing service.
#
# 1. It tries to find a process which is using specified port.  If the
#    process is not same as naming-service to be started by this
#    script, script will be aborted.
#
# 2. Next, it checks if the process is started from init script. If
#    the process is started from the init script, it tries to stop it
#    by the script.
#
# 3. The process is not started by init script, it tries to stop the
#    process by pkill command.
#
stop_existing_ns()
{
    debug "---stop_existing_ns"

    # Find a process which is using specified port.
    specified_port_used_check

    # Started form /etc/init.d/ script?
    is_started_from_init $pname_of_nsport $pid_of_nsport

    # omniNames is not started by init script
    if test $? -ne 0; then
        debug "$pname might not be started from init script."
        if test "x$pid_of_nsport" != "x" ; then
            echo "$pname (pid: $pid_of_nsport) is running"

            # Restart naming service
            if test "x$FORCEKILL" = "x" ; then
                if test "x$STOPNAMESERVICE" = "x" ; then
		            read -p "Kill anyway and start $pname again? (y/N)" killns
	            else
                    read -p "Kill anyway? (y/N)" killns
		        fi
                if test "x$killns" != "xy" -a  "x$killns" != "xY"; then
                    echo "Aborting"
                    exit 1
                fi
	        fi
            if test "x$PASSWORD" = "x" ; then
                sudo kill -9 $pid_of_nsport
            else
                echo $PASSWORD | sudo -S kill -9 $pid_of_nsport
            fi
            echo "$pname (pid: $pid_of_nsport) are killed"
            debug "$pname (pid: $pid_of_nsport) are killed"
            delete_omninames_files
            return 0
        fi
        echo "No running $pname found. The process using the port $PORT "
        echo "cannot be estimated. Arboting"
        exit 1
    fi
    # omniNames is started by init script
    stop_omninames_by_init_script
    return 0
}

#------------------------------------------------------------
# omniNames specific functions
#------------------------------------------------------------
#
# start_omninames
#
# This function starts omniNames and checks it is properly started.
# If omniNames could not be started properly, this function returns 1.
#
start_omninames()
{
    debug "---start_omninames"
    echo 'Starting omniORB omniNames: '$hostname':'$PORT
    delete_omninames_files
    if test "x$PASSWORD" = "x" ; then
        $cosnames -start $PORT -logdir $currdir &
    else
        echo $PASSWORD | sudo -S $cosnames -start $PORT -logdir $currdir &
    fi
    ret=$!
    sleep 1
    debug "return code of omniNames:" $ret
    omnip=`ps $! | wc -l`
    if test $omnip -gt 1; then
        echo "omniNames properly started"
        exit 0
    fi
    return 1 
}

omniname()
{
    # Check cosname variable is properly set
    check_cosname

    # Starting omniNames 
    if test "x$STOPNAMESERVICE" = "x" ; then
      start_omninames
      echo "omniNames was not properly started."
    fi

    # Stopping existing name service
    stop_existing_ns

    # Try to start omniNames again
    if test "x$STOPNAMESERVICE" = "x" ; then
      start_omninames
      echo "omniNames was not properly started."
    fi
}

#------------------------------------------------------------
# TAO Naming_Service specific functions
#------------------------------------------------------------
#
# start_taonames
#
# This function starts TAO Naming_Service and checks it is properly started.
# If TAO Naming_Service could not be started properly, this function returns 1.
#
start_taonames()
{
    if test ! -f $cosnames ; then
	echo "TAO Naming_Service not found. Aborting."
	exit 1
    fi
    echo 'Starting TAO Naming_Service: '$hostname':'$PORT
    $cosnames -m 0 -ORBListenEndpoints iiop://:$PORT &
    ret=$!
    sleep 1
    debug "return code of TAO Naming_Service:" $ret
    omnip=`ps $! | wc -l`
    if test $omnip -gt 1; then
	echo "TAO Naming_Service properly started"
	exit 0
    fi
    return 1

}

taonames()
{
    # Check cosname variable is properly set
    check_cosname

    # Starting omniNames
    start_taonames
    echo "TAO Naming_Service was not properly started."

    # Stopping existing name service
    stop_existing_ns

    # Try to start omniNames again
    start_taonames
    echo "TAO Naming_Service was not properly started."
}



#------------------------------------------------------------
# main
#------------------------------------------------------------
get_opt $@

case $orb in
	omniORB)
		omniname
		;;
	TAO)
		taonames
		;;
	*)
		usage
		;;
esac
